//
//  ObjCRuntime.m
//  winterTest
//
//  Created by wwinter on 15/12/20.
//  Copyright © 2015年 winter. All rights reserved.
//

#import "ObjCRuntime.h"
#import <objc/runtime.h>

NSDictionary *getPropertyListOfObject(NSObject *object)
{
    return getPropertyListOfClass([object class]);
}

NSDictionary *getPropertyListOfClass(Class cls)
{
    NSMutableDictionary *propertyListDict = [NSMutableDictionary dictionary];
    
    unsigned int outCount, i;
    objc_property_t *propreties = class_copyPropertyList(cls, &outCount);
    
    for (i = 0; i < outCount; i++) {
        objc_property_t property = propreties[i];
        const char *proName = property_getName(property);
        const char *proType = property_getAttributes(property);
        
        if (proType && proName) {
            NSArray *anAttribute = [[NSString stringWithUTF8String:proType] componentsSeparatedByString:@","];
            NSString *aType = anAttribute[0];
            
            // 暂时不能去掉前缀 T@" 和 后缀 " 需要用于区分标量与否
//            if ([aType hasPrefix:@"T@\""]) {
//                aType = [aType substringWithRange:NSMakeRange(3, [aType length]-4)];
//            } else {
//                aType = [aType substringFromIndex:1];
//            }
            
            [propertyListDict setObject:aType forKey:[NSString stringWithUTF8String:proName]];
        }
    }
    free(propreties);
    
    return propertyListDict;
}

// 实例方法就交换实例方法 类方法就交换类方法
void swizzle(Class cls, SEL orignSEL, SEL newSEL)
{
    // 先判断 是实例方法
    Method orignMethod = class_getInstanceMethod(cls, orignSEL);
    Method newMethod = nil;
    
    if (!orignMethod) {
        // 类方法
        orignMethod = class_getClassMethod(cls, orignSEL);
        if (!orignMethod) {
            return;
        }
        newMethod = class_getClassMethod(cls, newSEL);
        if (!newMethod) {
            return;
        }
    } else {
        // 实例方法
        newMethod = class_getInstanceMethod(cls, newSEL);
        if (!newMethod) {
            return;
        }
    }
    
    // 自身已经有方法就不添加，直接交换
    if (class_addMethod(cls, orignSEL, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
        class_replaceMethod(cls, newSEL, method_getImplementation(orignMethod), method_getTypeEncoding(orignMethod));
    } else {
        method_exchangeImplementations(orignMethod, newMethod);
    }
}

